package com.gitee.cloorc.dnser;


import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author z0228
 */
public class DnserApplication {
	private static final ObjectMapper OM = new ObjectMapper();
	private static final Pattern AKSK = Pattern.compile("[^:]+:[^:]+");
	private static final Pattern HOST = Pattern.compile("([^.]+)(\\.[^.]+)*");
	private static final PrintStream LOG;

	static {
		PrintStream ps;
		try {
			ps = new PrintStream(new FileOutputStream("dnser.log", true));
		} catch (FileNotFoundException e) {
			ps = System.out;
		}
		LOG = ps;
	}

	public static void main(String[] args) throws ClientException, IOException {
		if (args.length < 2 || !AKSK.matcher(args[0]).matches()
			|| !HOST.matcher(args[1]).matches()) {
			LOG.println("Usage: java -jar dnser ak:sk rr.domain.com [www.baidu.com]");
			return;
		}
		//域名SDK请使用固定值"cn-hangzhou"
		String regionId = "cn-hangzhou";
		String accessKeyId = args[0].substring(0, args[0].indexOf(":"));
		String accessKeySecret = args[0].substring(accessKeyId.length() + 1);
		String rr = args[1].substring(0, args[1].indexOf("."));
		String domain = args[1].substring(rr.length() + 1);
		String remote = args.length > 2 && null != args[2] && args[2].length() > 0 ?
			args[2] : "www.baidu.com";
		IClientProfile profile = DefaultProfile.getProfile(regionId,
			accessKeyId, accessKeySecret);
		DefaultProfile.addEndpoint("cn-hangzhou", "Domain", "domain.aliyuncs.com");
		IAcsClient client = new DefaultAcsClient(profile);

		String recordId = null;
		String type = null;
		String ipv4 = null;

		{
			CommonRequest request = new CommonRequest();
			request.setMethod(MethodType.POST);
			request.setDomain("alidns.aliyuncs.com");
			request.setVersion("2015-01-09");
			request.setAction("DescribeDomainRecords");
			request.putQueryParameter("DomainName", domain);
			request.putQueryParameter("RRKeyWord", rr);
			CommonResponse response = client.getCommonResponse(request);
			runtime(null != response && null != response.getData(),
				null != response ? response.getData() : "Unable to get response.");
			Map map = OM.readValue(response.getData(), HashMap.class);
			runtime(0 < (Integer) map.get("TotalCount") && map.containsKey("DomainRecords"),
				"Invalid response : " + response.getData());
			List<Map> records = (List<Map>) ((Map) map.get("DomainRecords")).get("Record");
			for (Map record : records) {
				if (record.containsKey("RR") && rr.equals(record.get("RR"))) {
					recordId = (String) record.get("RecordId");
					type = (String) record.get("Type");
					ipv4 = (String) record.get("Value");
					break;
				}
			}
			runtime(null != recordId && null != type && null != ipv4,
				"Record not found : " + response.getData());
		}

		{
			final DatagramSocket socket = new DatagramSocket();
			socket.connect(InetAddress.getByName(remote), 80);
			final String address = socket.getLocalAddress().getHostAddress();
			runtime(null != address, "Unable to get IP address.");
			if (address.equals(ipv4)) {
				LOG.println("IP address not changed.");
				return;
			} else {
				ipv4 = address;
			}
		}

		{
			CommonRequest request = new CommonRequest();
			request.setMethod(MethodType.POST);
			request.setDomain("alidns.aliyuncs.com");
			request.setVersion("2015-01-09");
			request.setAction("UpdateDomainRecord");
			request.putQueryParameter("RecordId", recordId);
			request.putQueryParameter("RR", rr);
			request.putQueryParameter("Type", type);
			request.putQueryParameter("Value", ipv4);
			CommonResponse response = client.getCommonResponse(request);
			System.out.println(response.getData());
		}
	}

	private static void runtime(boolean expression, String message) {
		if (!expression) {
			throw new RuntimeException(message);
		}
	}
}
